#include <SystemCore.h>
#include <SystemCollections.h>
#include <SystemIO.h>
#include <SystemNet.h>
#pragma once

namespace Milan { namespace Net {
	class Download
	{
	public:
		/// <summary>
		/// Grabs a text file from the given URL.  If URL is null, then we iterate our URLs.
		/// </summary>
		/// <param name="url"></param>
		/// <returns>The text file or null on communication error.</returns>
		static std::string GetTextFile(System::Uri url);
		/// <summary>
		/// Copies a Web file via HTTP to a local file.
		/// </summary>
		/// <param name="url"></param>
		/// <param name="localFile"></param>
		static void Copy(System::Uri url, const char * localFile);
	};

	/// <summary>
	/// Handles uploading of files in various configurations.
	/// </summary>
	class Upload
	{
		/// <summary>
		/// Posts a crash dump to the server.
		/// </summary>
		/// <returns></returns>
		static std::string PostCrashDump(int processId, const System::Uri &uri);
		/// <summary>
		/// Uploads a file to a multi-part form, with optional post field data, cookies and header data.
		/// This is useful, for say, posting to an HTML form with a file element.  Currently accepts only one file.
		/// </summary>
		/// <param name="requestUri">The URI to use to post the data</param>
		/// <param name="postData">A NameValueCollection containing form fields to post along with file data</param>
		/// <param name="fileData">An open, positioned stream containing the file or binary data</param>
		/// <param name="fileName">Optionally, a name to assign to the uploaded file.</param>
		/// <param name="fileFieldName">Optional, a form field to give to the uploaded file.</param>
		/// <param name="fileContentType">MIME Content type, which if null or empty, attempts to determine from the registry.</param>
		/// <param name="cookies">Optional, (can be null). Used to send and retrieve cookies for maintaining state between calls.</param>
		/// <param name="headers">Optional, headers to be added to request.</param>
		/// <returns>WebResponse object, which can be used to read the request</returns>
		static System::Net::WebResponse PostFile(const System::Uri &requestUri, const System::Collections::Specialized::NameValueCollection &postData, System::IO::Stream & fileData, const char * fileName = nullptr,
			const char * fileFieldName = nullptr, const char * fileContentType = nullptr, const System::Net::CookieContainer * cookies = nullptr, const System::Collections::Specialized::NameValueCollection * headers = nullptr);

		/// <summary>
		/// Uploads a file using a multi-part/form-data POST.
		/// </summary>
		/// <param name="requestUri">The URI to use to post the data</param>
		/// <param name="postData">A NameValueCollection containing form fields to post along with file data</param>
		/// <param name="filePath">The path of the file to upload</param>
		/// <param name="fileFieldName">Optional, a form field name to assign to the uploaded file data, or "file" will be used if null or empty.</param>
		/// <param name="fileContentType">MIME Content type, which if null or empty, attempts to determine from the registry.</param>
		/// <param name="cookies">Optional, can pass null. Used to send and retrieve cookies. 
		/// Pass the same instance to subsequent calls to maintain state if required.</param>
		/// <param name="headers">Optional, headers to be added to request.</param>
		/// <returns></returns>
		static System::Net::WebResponse PostFile(const System::Uri & requestUri, const System::Collections::Specialized::NameValueCollection &postData, const char * filePath, const char * fileFieldName = nullptr,
			const char * fileContentType = nullptr, const System::Net::CookieContainer * cookies = nullptr, const System::Collections::Specialized::NameValueCollection *headers = nullptr);

		/// <summary>
		/// Simply post a file and some fields to a form, returning the response.
		/// </summary>
		/// <param name="uri">Where to post</param>
		/// <param name="filePath">Path to file to upload</param>
		/// <param name="postData">NameValueCollection with form name, value pairs</param>
		/// <returns>A null on error or the response from the server.  Can also throw an exception on connectivity error.</returns>
		static std::string PostFile(const System::Uri & uri, const char * filePath, const System::Collections::Specialized::NameValueCollection & postData = nullref);

		/// <summary>
		/// Simply post a file and some fields to a form, returning the response.
		/// </summary>
		/// <param name="uri">Where to post</param>
		/// <param name="text">The</param>
		/// <param name="postData">NameValueCollection with form name, value pairs</param>
		/// <returns>A null on error or the response from the server.  Can also throw an exception on connectivity error.</returns>
		static std::string PostTextAsFile(const System::Uri & uri, const char * text, const char *  fileName, const System::Collections::Specialized::NameValueCollection & postData = nullref);

		/// <summary>
		/// Post post vars only with no file.
		/// </summary>
		/// <param name="uri"></param>
		/// <param name="postData"></param>
		/// <returns></returns>
		static std::string PostVarsOnly(const System::Uri & uri, const System::Collections::Specialized::NameValueCollection & postData = nullref);

		/// <summary>
		/// Tries to query registry for content-type of supplied file name.
		/// </summary>
		/// <param name="fileName"></param>
		/// <param name="contentType"></param>
		/// <returns></returns>
		static bool TryGetContentType(const char * fileName, std::string & contentType);
	};


} }
